package com.flute.framework.search.result.xmlresult;

import java.util.ArrayList;
import java.util.List;

/**
 * xml节点封装类
 * 
 * @author xuweiwei
 * 
 */
public class Node {
	/**
	 * 属性集合
	 */
	private List<Attribute> attList = new ArrayList<Attribute>();
	/**
	 * 字节点集合
	 */
	private List<Node> subNodeList = new ArrayList<Node>();
	/**
	 * 节点名
	 */
	private String name = null;
	/**
	 * 父节点
	 */
	private Node father = null;
	/**
	 * 节点内容
	 */
	private String content = null;

	public Node(String name) {
		setName(name);
	}

	public Node(String name, Node father) {
		this(name);
		setFather(father);
	}

	public Node(String name, String content) {
		this(name);
		setContent(content);
	}

	public Node(String name, String content, Node father) {
		this(name, content);
		setFather(father);
	}

	/**
	 * 获取节点的开始标签
	 * 
	 * @return 节点的开始标签
	 */
	public String getXmlStartTage() {
		StringBuilder result = new StringBuilder();
		result.append("<");
		result.append(name);
		for (int i = 0; i < getAttList().size(); i++) {
			result.append(" ");
			Attribute a = getAttList().get(i);
			result.append(a.toString());
		}
		result.append(">");
		return result.toString();
	}

	@Override
	public String toString() {
		return toXmlString();
	}

	/**
	 * 获取该节点的xml结束标签字符串
	 * 
	 * @return 该节点的xml结束标签字符串
	 */
	public String getXmlEndTage() {
		StringBuilder result = new StringBuilder();
		result.append("</");
		result.append(getName());
		result.append(">");
		return result.toString();
	}

	/**
	 * 获取内容为空时节点的xml字符串
	 * 
	 * @return 内容为空时节点的xml字符串
	 */
	public String getNullContentString() {
		String result = getXmlStartTage();
		result = result.substring(0, result.length() - 1) + "/>";
		return result;
	}

	/**
	 * 获取无子节点的xml字符串
	 * 
	 * @return 无子节点的xml字符串
	 */
	public String getFinalNodeXml() {
		StringBuilder result = new StringBuilder();
		if (getContent() != null) {
			result.append(getXmlStartTage());
			result.append(getCDATAXml());
			result.append(getXmlEndTage());
		} else {
			result.append(getNullContentString());
		}
		return result.toString();

	}

	/**
	 * 获取文本域的xml字符串
	 * 
	 * @return 文本域的xml字符串
	 */
	public String getCDATAXml() {
		StringBuilder result = new StringBuilder();
		if (getContent() != null) {
			result.append("<![CDATA[");
			result.append(getContent());
			result.append("]]>");
		}
		return result.toString();
	}

	/**
	 * @return 获取节点的xml字符串
	 */
	public String toXmlString() {
		StringBuilder result = new StringBuilder();
		if (isFinalNode()) {
			result.append(getFinalNodeXml());
		} else {
			result.append(getXmlStartTage());
			for (int i = 0; i < getSubNodeList().size(); i++) {
				result.append(getSubNodeList().get(i).toXmlString());
			}
			result.append(getXmlEndTage());
		}
		return result.toString();
	}

	/**
	 * 判断是否是指定节点的父节点
	 * 
	 * @param node
	 *            指定节点
	 * @return 是否是指定节点的父节点
	 */
	public boolean isFather(Node node) {
		boolean isFather = Boolean.FALSE;
		if (node != null) {
			for (int i = 0; i < subNodeList.size(); i++) {
				if (node == subNodeList.get(i)
						|| node.equals(subNodeList.get(i))) {
					isFather = Boolean.TRUE;
					break;
				}
			}
		}
		return isFather;
	}

	/**
	 * 判断是否是指定节点的子节点
	 * 
	 * @param node
	 *            指定节点
	 * @return 是否是指定节点的子节点
	 */
	public boolean isSub(Node node) {
		boolean isSub = Boolean.FALSE;
		if (node != null) {
			for (int i = 0; i < node.getSubNodeList().size(); i++) {
				if (this == node.getSubNodeList().get(i)
						|| this.equals(node.getSubNodeList().get(i))) {
					isSub = Boolean.TRUE;
					break;
				}
			}
		}
		return isSub;
	}

	@Override
	public int hashCode() {
		return name.hashCode() + content.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return Boolean.FALSE;
		}
		if (this == obj) {
			return Boolean.TRUE;
		}
		if (!(obj instanceof Node)) {
			return Boolean.FALSE;
		}
		Node node = (Node) obj;
		return this.father == node.getFather() && this.name != null
				&& this.name.equals(node.getName());
	}

	/**
	 * 判断是否是指定节点的兄弟节点
	 * 
	 * @param node
	 *            指定节点
	 * @return 是否是指定节点的兄弟节点
	 */
	public boolean isBrother(Node node) {
		return this.father == node.father;
	}

	/**
	 * 增加子节点
	 * 
	 * @param n
	 *            字节点名
	 * @return 当前节点
	 */
	public Node addSub(Node n) {
		if (n != null) {
			boolean addFlag = Boolean.TRUE;
			for (int i = 0; i < getSubNodeList().size(); i++) {
				if (getSubNodeList().get(i) == n) {
					addFlag = Boolean.FALSE;
					break;
				}
			}
			if (addFlag) {
				getSubNodeList().add(n);
			}
		}
		return this;
	}

	/**
	 * 给当前节点加属性
	 * 
	 * @param a
	 *            属性
	 * @return 当前节点
	 */
	public Node addAtt(Attribute a) {
		if (a != null) {
			boolean addFlag = Boolean.TRUE;
			for (int i = 0; i < getSubNodeList().size(); i++) {
				if (getSubNodeList().get(i).getName().equals(a.getName())) {
					addFlag = Boolean.FALSE;
				}
			}
			if (addFlag) {
				getAttList().add(a);
			}
		}
		return this;
	}

	/**
	 * @param father
	 *            节点
	 * @return 父节点
	 */
	public Node joinFather(Node father) {
		boolean addFather = Boolean.FALSE;
		if (father != null && getFather() == null) {
			addFather = Boolean.TRUE;
			for (int i = 0; i < father.getSubNodeList().size(); i++) {
				if (getSubNodeList().get(i) == this) {
					addFather = Boolean.FALSE;
					break;
				}
			}
		}
		if (addFather) {
			father.getSubNodeList().add(this);
			return father;
		} else {
			throw new NullPointerException();
		}
	}

	/**
	 * 判断本节点是否是根节点
	 * 
	 * @return 本节点是否是根节点
	 */
	public boolean isRoot() {
		return this.getFather() == null;
	}

	/**
	 * 判断本节点是否是叶节点
	 * 
	 * @return 本节点是否是叶节点
	 */
	public boolean isFinalNode() {
		return getSubNodeList().size() == 0;
	}

	public void setFather(Node father) {
		this.father = father;
	}

	public Node getFather() {
		return father;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name.trim();
	}

	public List<Attribute> getAttList() {
		return attList;
	}

	public void setAttList(List<Attribute> attList) {
		this.attList = attList;
	}

	public List<Node> getSubNodeList() {
		return subNodeList;
	}

	public void setSubNodeList(List<Node> subNodeList) {
		this.subNodeList = subNodeList;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	/**
	 * 通过xpath表达式获取指定节点
	 * 
	 * @param xpath
	 *            xpath表达式
	 * @return xpath表达式指定节点
	 */
	public Node getFirstNodeByXpath(String xpath) {
		return getFirstNodeByXpath(this, xpath);
	}

	/**
	 * 通过xpath表达式获取指定节点
	 * 
	 * @param root
	 *            节点
	 * @param xpath
	 *            xpath表达式
	 * @return xpath表达式指定节点
	 */
	public static Node getFirstNodeByXpath(Node root, String xpath) {
		String[] xpaths = xpath.substring(2).split("/");
		Node curr = root;
		if (root.getName().equals(xpaths[0])) {
			for (int i = 1; i < xpaths.length; i++) {
				for (Node c : curr.getSubNodeList()) {
					if (c.getName().equals(xpaths[i])) {
						curr = c;
						continue;
					}
				}
			}
		}
		return curr;
	}

	/**
	 * 节点解析
	 * 
	 * @param name
	 *            xml节点xpath表达式
	 * @return xml节点
	 */
	public static Node parser(String name) {
		if (XmlParserUtil.isValid(name)) {
			return parser(name, null);
		} else {
			throw new TagNotFoundException();
		}
	}

	/**
	 * 节点解析
	 * 
	 * @param name
	 *            xml节点xpath表达式
	 * @param content
	 *            内容
	 * @return xml节点
	 */
	public static Node parser(String name, String content) {
		if (XmlParserUtil.isValid(name)) {
			return new Node(name, content);
		} else {
			throw new TagNotFoundException();
		}
	}

	public static void main(String[] args) {
		Node n = new Node("root");
		Node s = new Node("song");
		n.addSub(s);
		System.out.println(getFirstNodeByXpath(n, "//root//song").getName());
	}
}
